using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace EntityKit.Editor
{
    public sealed class ScriptReferenceFinder : EditorWindow
    {
        private sealed class Data
        {
            public struct Labels
            {
                public const string ButtonFindMatches = "查找所有Prefab上组件";
                public const string HeaderFindComponentsSuccess = "匹配结果:";
                public const string HeaderFindComponentsFail = "未找到匹配项。";
                public const string HeaderScriptFinder = "脚本引用查找器";
                public const string HeaderShouldRecurse = "递归查找依赖项（警告：非常慢）";
                public const string HeaderTargetObjectField = "选择目标脚本";
                public const string WindowTitle = "脚本引用查找器";
            }

            public static readonly Vector2 WindowSize = new Vector2
            {
                x = 800.0f,
                y = 400.0f
            };
        }

        #region Fields

        private MonoScript targetComponent;
        private bool shouldRecurse = false;
        private Vector2 scrollPosition = Vector2.zero;
        private List<string> results;
        private string selectedResult = "";

        #endregion

        #region Unity Methods

        /// <summary>
        /// 显示脚本引用查找窗口
        /// </summary>
        public static void ShowWindow()
        {
            // 获取现有打开的窗口，如果没有则创建一个新窗口
            var window = (ScriptReferenceFinder)GetWindow(typeof(ScriptReferenceFinder), true, Data.Labels.WindowTitle);
            window.minSize = Data.WindowSize;
            window.maxSize = Data.WindowSize;
            window.Show();
        }

        void OnEnable()
        {
            wantsMouseMove = true;
        }

        void OnGUI()
        {
            HandleEvents();

            DrawGUIBackground();
            DrawGUIControls();
            DrawGUIResults();
        }

        #endregion

        #region Input Events

        /// <summary>
        /// 处理输入事件
        /// </summary>
        private void HandleEvents()
        {
            var e = UnityEngine.Event.current;

            switch (e.type)
            {
                case EventType.MouseMove:
                    OnMouseMove();
                    break;
            }
        }

        #region Mouse Events

        /// <summary>
        /// 鼠标移动事件处理
        /// </summary>
        private void OnMouseMove()
        {
            Repaint();
        }

        #endregion

        #endregion

        #region Draw GUI

        /// <summary>
        /// 绘制背景元素
        /// </summary>
        private static void DrawGUIBackground()
        {
            EditorGUI.DrawRect(new Rect(0.0f, 0.0f, 800.0f, 30.0f), new Color32(60, 60, 60, 255));

            EditorGUI.DrawRect(new Rect(0.0f, 30.0f, 800.0f, 370.0f), new Color32(90, 90, 90, 255));
            EditorGUI.DrawRect(new Rect(10.0f, 40.0f, 780.0f, 350.0f), new Color32(60, 60, 60, 255));
            EditorGUI.DrawRect(new Rect(12.0f, 42.0f, 776.0f, 346.0f), new Color32(70, 70, 70, 255));

            EditorGUI.DrawRect(new Rect(20.0f, 225.0f, 760.0f, 155.0f), new Color32(60, 60, 60, 255));
            EditorGUI.DrawRect(new Rect(22.0f, 227.0f, 756.0f, 151.0f), new Color32(90, 90, 90, 255));
        }

        /// <summary>
        /// 绘制控制界面元素
        /// </summary>
        private void DrawGUIControls()
        {
            // 绘制标题
            GUIStyle headerStyle = CreateHeaderStyle(16, FontStyle.Bold, TextAnchor.MiddleCenter);
            EditorGUILayout.LabelField(Data.Labels.HeaderScriptFinder, headerStyle);
            
            // 绘制目标脚本选择标签
            GUIStyle targetObjectLabelStyle = CreateHeaderStyle(12, FontStyle.Normal, TextAnchor.UpperLeft);
            targetObjectLabelStyle.contentOffset = new Vector2(17, 40);
            EditorGUILayout.LabelField(Data.Labels.HeaderTargetObjectField, targetObjectLabelStyle);
            
            // 绘制目标脚本选择框
            targetComponent = (MonoScript)EditorGUI.ObjectField(
                new Rect(20.0f, 80.0f, 762.0f, 17.0f), 
                targetComponent,
                typeof(MonoScript), 
                false);
            
            // 绘制递归依赖选项标签
            GUIStyle recurseLabelStyle = CreateHeaderStyle(12, FontStyle.Bold, TextAnchor.UpperLeft);
            recurseLabelStyle.contentOffset = new Vector2(17, 80);
            EditorGUILayout.LabelField(Data.Labels.HeaderShouldRecurse, recurseLabelStyle);
            
            // 绘制递归依赖选项开关
            shouldRecurse = EditorGUI.Toggle(new Rect(18.0f, 135.0f, 20.0f, 20.0f), shouldRecurse);

            // 绘制查找按钮
            if (GUI.Button(new Rect(20.0f, 160.0f, 760.0f, 20.0f), Data.Labels.ButtonFindMatches))
            {
                ActionSearchForComponent();
            }
        }

        /// <summary>
        /// 绘制结果界面元素
        /// </summary>
        private void DrawGUIResults()
        {
            if (results != null)
            {
                GUIStyle resultHeaderStyle = CreateHeaderStyle(12, FontStyle.Bold, TextAnchor.UpperLeft);
                resultHeaderStyle.contentOffset = new Vector2(17, 130);
                
                if (results.Count == 0)
                {
                    EditorGUILayout.LabelField(Data.Labels.HeaderFindComponentsFail, resultHeaderStyle);
                }
                else
                {
                    EditorGUILayout.LabelField(Data.Labels.HeaderFindComponentsSuccess, resultHeaderStyle);
                    GUILayout.BeginArea(new Rect(22.0f, 227.0f, 756.0f, 151.0f));
                    scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
                    
                    // 创建按钮样式
                    GUIStyle buttonMatchStyle = new GUIStyle
                    {
                        normal = new GUIStyleState
                        {
                            background = CreateButtonTexture(new Color32(100, 100, 100, 255), new Color32(80, 80, 80, 255), 756, 30, 4),
                            textColor = new Color32(255, 255, 255, 255)
                        },
                        hover = new GUIStyleState
                        {
                            background = CreateButtonTexture(new Color32(130, 130, 200, 255), new Color32(90, 90, 160, 255), 756, 30, 4),
                            textColor = new Color32(255, 255, 255, 255)
                        },
                        fontStyle = FontStyle.Bold,
                        fontSize = 12,
                        padding = new RectOffset(5, 0, 6, 0)
                    };
                    
                    GUIStyle buttonMatchSelectedStyle = new GUIStyle
                    {
                        normal = new GUIStyleState
                        {
                            background = CreateButtonTexture(new Color32(110, 110, 180, 255), new Color32(70, 70, 140, 255), 756, 30, 4),
                            textColor = new Color32(255, 255, 255, 255)
                        },
                        hover = new GUIStyleState
                        {
                            background = CreateButtonTexture(new Color32(110, 110, 180, 255), new Color32(70, 70, 140, 255), 756, 30, 4),
                            textColor = new Color32(255, 255, 255, 255)
                        },
                        fontStyle = FontStyle.Bold,
                        fontSize = 12,
                        padding = new RectOffset(5, 0, 6, 0)
                    };

                    foreach (string s in results)
                    {
                        GUIStyle activeStyle = s == selectedResult ? buttonMatchSelectedStyle : buttonMatchStyle;
                        GUILayoutOption[] layoutOptions = {
                            GUILayout.Width(756.0f),
                            GUILayout.Height(30.0f)
                        };
                        
                        if (GUILayout.Button(s, activeStyle, layoutOptions))
                        {
                            Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(s);
                            selectedResult = s;
                        }
                    }

                    EditorGUILayout.EndScrollView();
                    GUILayout.EndArea();
                }
            }
        }

        /// <summary>
        /// 创建标题样式
        /// </summary>
        /// <param name="fontSize">字体大小</param>
        /// <param name="fontStyle">字体样式</param>
        /// <param name="alignment">对齐方式</param>
        /// <returns>GUI样式</returns>
        private GUIStyle CreateHeaderStyle(int fontSize, FontStyle fontStyle, TextAnchor alignment)
        {
            var style = new GUIStyle(GUI.skin.label)
            {
                fontSize = fontSize,
                fontStyle = fontStyle,
                alignment = alignment,
                fixedWidth = 800,
                fixedHeight = 30
            };
            return style;
        }
        
        /// <summary>
        /// 创建带底部边框的按钮纹理
        /// </summary>
        /// <param name="bgCol">背景颜色</param>
        /// <param name="borderCol">边框颜色</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="borderThickness">边框厚度</param>
        /// <returns>纹理</returns>
        private Texture2D CreateButtonTexture(Color bgCol, Color borderCol, int width, int height, int borderThickness)
        {
            Color[] pix = new Color[width * height];
            Color[] backgroundPixels = new Color[width * height];
            
            // 填充背景色
            for (int i = 0; i < backgroundPixels.Length; i++)
            {
                backgroundPixels[i] = bgCol;
            }

            // 添加底部边框
            int offset = width * borderThickness;
            offset = offset <= width * height ? offset : width * height;

            for (int i = 0; i < offset; i++)
            {
                backgroundPixels[i] = borderCol;
            }

            var result = new Texture2D(width, height);
            result.SetPixels(backgroundPixels);
            result.Apply();

            return result;
        }

        #endregion

        #region Actions

        /// <summary>
        /// 查找组件引用的操作
        /// </summary>
        private void ActionSearchForComponent()
        {
            // 获取目标脚本的路径
            string targetPath = AssetDatabase.GetAssetPath(targetComponent);
            
            // 获取所有prefab文件
            string[] allPrefabs = GetAllPrefabs();
            results = new List<string>();

            // 遍历所有prefab文件查找引用
            foreach (string prefab in allPrefabs)
            {
                string[] single = new string[] { prefab };
                string[] dependencies = AssetDatabase.GetDependencies(single, shouldRecurse);
                foreach (string dependentAsset in dependencies)
                {
                    if (dependentAsset == targetPath)
                    {
                        results.Add(prefab);
                    }
                }
            }
        }

        #endregion

        #region Utilities

        /// <summary>
        /// 获取所有prefab文件路径
        /// </summary>
        /// <returns>prefab文件路径数组</returns>
        public static string[] GetAllPrefabs()
        {
            string[] temp = AssetDatabase.GetAllAssetPaths();
            List<string> result = new List<string>();
            foreach (string s in temp)
            {
                if (s.Contains(".prefab"))
                {
                    result.Add(s);
                }
            }

            return result.ToArray();
        }

        #endregion
    }
}